package com.diaohw.platform.framework.web.config;

import com.diaohw.platform.common.obj.thread.RequestThread;
import com.diaohw.platform.common.util.JacksonUtil;
import com.diaohw.platform.framework.web.interceptor.WebMvcInterceptor;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Collections;
import java.util.List;

/**
 * @author 刁海文
 * @since 2023/6/11 17:44
 */
@Slf4j
@Order(999)
@Configuration
public class GlobalWebConfig implements WebMvcConfigurer {

    @Resource
    private WebMvcInterceptor webMvcInterceptor;

    /**
     * jackson 序列化配置
     */
    public static MappingJackson2HttpMessageConverter jackson2HttpMessageConverter() {
        MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();

        jackson2HttpMessageConverter.setObjectMapper(JacksonUtil.createObjectMapper());

        return jackson2HttpMessageConverter;
    }

    @Bean
    public ClientHttpRequestFactory getFactory() {

        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setReadTimeout(5000);
        factory.setConnectTimeout(5000);
        return factory;
    }

    @Bean
    @ConditionalOnMissingBean(RestTemplate.class)
    public RestTemplate restTemplateBean(ClientHttpRequestFactory clientHttpRequestFactory) {
        RestTemplateBuilder builder = new RestTemplateBuilder();

        builder.messageConverters(jackson2HttpMessageConverter());
        builder.requestFactory(() -> clientHttpRequestFactory);
        RestTemplate template = builder.build();

        template.setInterceptors(Collections.singletonList((request, body, execution) -> {
            //修改请求的header对象
            request.getHeaders().addAll(RequestThread.headers());
            //执行请求
            return execution.execute(request, body);
        }));
        return template;
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(jackson2HttpMessageConverter());  // jackson
    }

    @Bean
    public JavaTimeModule javaTimeModule() {
        return JacksonUtil.javaTimeModule();
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        log.info("开启静态资源映射...");
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        registry.addResourceHandler("/swagger-ui/**").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 自定义拦截器，logger MDC 请求信息初始化
        registry.addInterceptor(webMvcInterceptor)
                .excludePathPatterns("/doc.html", "/swagger-ui.html", "/swagger-ui/**", "/favicon.ico", "/webjars/**", "/v3/**", "/error")
                .addPathPatterns("/**");
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowCredentials(true)
                //.allowedOrigins("*")
                .allowedOriginPatterns("*")
                .allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS")
                .allowedMethods("*")
                .exposedHeaders("*");
    }

}
